package com.gp.ssmplus.base.core.mybatis.base.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gp.ssmplus.base.core.mybatis.base.mapper.SuperMapper;
import com.gp.ssmplus.base.core.mybatis.base.service.IBaseService;
import com.gp.ssmplus.base.core.mybatis.common.utils.ApiAssert;
import com.gp.ssmplus.base.core.mybatis.common.utils.FlymeUtils;
import com.gp.ssmplus.base.core.mybatis.common.utils.JsonUtils;
import com.gp.ssmplus.base.core.mybatis.common.utils.SpringContextHolder;
import com.gp.ssmplus.base.core.mybatis.entity.EntityMap;
import com.gp.ssmplus.base.core.mybatis.interceptor.*;
import com.gp.ssmplus.base.core.mybatis.model.ResultBody;
import com.gp.ssmplus.base.core.mybatis.query.CriteriaDelete;
import com.gp.ssmplus.base.core.mybatis.query.CriteriaQuery;
import com.gp.ssmplus.base.core.mybatis.query.CriteriaSave;
import com.gp.ssmplus.base.core.mybatis.query.CriteriaUpdate;
import org.apache.ibatis.annotations.Param;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;

import javax.annotation.Resource;
import java.util.List;

/**
 * 使用abstract是因为不能实例化，子类比需继承BaseServiceImpl  M extends SuperMapper<T>指的M类型必须是SuperMapper<T>的子类
 * @date: 2018/12/24 12:49
 * @desc: 父类service
 */
public abstract class BaseServiceImpl<M extends SuperMapper<T>, T> extends ServiceImpl<M , T> implements IBaseService<T> {

    @Autowired
    public ApplicationContext applicationContext;

    @Resource
    public AutowireCapableBeanFactory spring;

    @Resource
    public SqlSessionTemplate sqlSession;

    @Autowired
    public ApplicationEventPublisher publisher;


    public void pushEvent(ApplicationEvent applicationEvent) {
        applicationContext.publishEvent(applicationEvent);
    }


    /**
     * 自定分页方法,可通过自定义处理器扩展
     */
    public ResultBody pageList(CriteriaQuery<?> cq) {
        ResultBody resultBody = new ResultBody();
        EntityMap extra = resultBody.getExtra();
        Boolean hanHandler = false;
        //扩展事件
        PageInterceptor pageInterceptor = SpringContextHolder.getHandler(cq.getHandlerName(), PageInterceptor.class);
        if (ObjectUtils.isNotEmpty(pageInterceptor)) {
            hanHandler = true;
            //执行校验
            resultBody = pageInterceptor.validate(cq);
        }
        if (resultBody.isOk()) {
            if (hanHandler) {
                pageInterceptor.prepare(cq, cq.getPageModel(), cq.getRequestMap());
            }
            Page page = cq.getPageParams();
            IPage<EntityMap> result = this.baseMapper.pageList(new Page(page.getCurrent(), page.getSize()), cq);
            EntityMap.setEnumConvertInterceptor(null);
            if (ObjectUtils.isNotNull(result)) {
                //扩展查询结果集
                if (hanHandler) {
                    pageInterceptor.complete(cq, result.getRecords(), extra);
                    pageInterceptor.complete(cq, result, extra);
                }
            }
            resultBody = resultBody.data(result).setExtra(extra);
        }
        return resultBody;
    }

    /**
     * selectEntityMap方法带扩展事件
     */
    public ResultBody get(CriteriaQuery<?> cq) {
        EntityMap result = new EntityMap();
        boolean hasHandler = false;
        ResultBody resultBody = new ResultBody();
        //获取扩展事件名称
        GetInterceptor getInterceptor = SpringContextHolder.getHandler(cq.getHandlerName(), GetInterceptor.class);
        //扩展查询条件
        if (FlymeUtils.isNotEmpty(getInterceptor)) {
            hasHandler = true;
            resultBody = getInterceptor.validate(cq, cq.getRequestMap());
        }
        if (resultBody.isOk()) {
            if (hasHandler) {
                getInterceptor.prepare(cq, cq.getRequestMap());
            }
            String condition = cq.getCustomSqlSegment();
            if (FlymeUtils.isEmpty(condition)) {
                ApiAssert.failure("查询条件不存在");
            }
            List<EntityMap> maps = baseMapper.selectEntityMap(cq);
            if (ObjectUtils.isNotNull(maps)) {
                result = maps.get(0);
                //扩展查询结果集
                if (hasHandler) {
                    getInterceptor.complete(cq, result);
                }
            }
        }

        return resultBody.data(result);
    }

    /**
     * 查询单个实体
     *
     * @param cq
     * @return
     */
    @Override
    public EntityMap findOne(CriteriaQuery cq) {
        EntityMap result = new EntityMap();
        List<EntityMap> maps = baseMapper.selectEntityMap(cq);
        if (ObjectUtils.isNotNull(maps)) {
            result = maps.get(0);
        }
        return result;
    }


    /**
     * 自定义更新
     */
    public ResultBody edit(CriteriaUpdate cu) {
        boolean isUpdate;
        //获取扩展事件
        UpdateInterceptor handler = SpringContextHolder.getHandler(cu.getHandlerName(), UpdateInterceptor.class);
        //更新前验证
        if (ObjectUtils.isNotNull(handler)) {
            ResultBody resultBody = handler.validate(cu, cu.getRequestMap());
            if (!resultBody.isOk()) {
                return resultBody;
            }
            handler.prepare(cu, cu.getRequestMap());
        }
        T obj = (T) FlymeUtils.getEntity(cu.getCls(), cu.getRequestMap());
        isUpdate = saveOrUpdate(obj);
        if (!isUpdate) {
            return ResultBody.failed("更新失败");
        }
        //更新成功后调用扩展事件
        if (FlymeUtils.isNotEmpty(handler)) {
            handler.complete(cu, cu.getRequestMap());
        }

        return ResultBody.ok("更新成功", obj);
    }

    /**
     * 自定义删除
     *
     * @param cd
     * @return
     */
    public ResultBody delete(CriteriaDelete cd) {
        //自定义扩展事件
        DeleteInterceptor handler = SpringContextHolder.getHandler(cd.getHandlerName(), DeleteInterceptor.class);
        if (FlymeUtils.isNotEmpty(handler)) {
            //执行校验
            ResultBody resultBody = handler.validate(cd, cd.getRequestMap());
            //验证失败直接返回
            if (!resultBody.isOk()) {
                return resultBody;
            }
            //执行条件预处理扩展
            handler.prepare(cd, cd.getRequestMap());
        }
        ApiAssert.isNotEmpty("删除条件不存在", cd.getCustomSqlSegment());
        int n;
        if (cd.getLogicalDelete()) {
            n = baseMapper.delete(cd);
        } else {
            //强制删除
            n = baseMapper.deleteByCq(cd);
        }
        if (n <= 0) {
            return ResultBody.failed("删除失败");
        }
        if (FlymeUtils.isNotEmpty(handler)) {
            handler.complete(cd, cd.getRequestMap());
        }

        return ResultBody.ok("删除成功", n);

    }


    /**
     * save方法带扩展事件
     */
    public ResultBody add(CriteriaSave cs) {
        SaveInterceptor handler = SpringContextHolder.getHandler(cs.getHandlerName(), SaveInterceptor.class);
        ResultBody resultBody = new ResultBody();
        //是否支持扩展条件
        boolean hasHandler = false;
        Boolean isSave = false;
        T obj = null;
        if (ObjectUtils.isNotNull(handler)) {
            hasHandler = true;
            resultBody = handler.validate(cs, cs.getRequestMap());
            if (!resultBody.isOk()) {
                return resultBody;
            }
            handler.prepare(cs, cs.getRequestMap());
            //获取自定义mapper
            BaseMapper mapper = handler.getMapper();
            //获取自定义实体
            obj = handler.getEntity(cs, cs.getRequestMap());
            if (ObjectUtils.isNotEmpty(obj)) {
                if (!cs.getSaveToRedis()) {
                    if (ObjectUtils.isNotEmpty(mapper)) {
                        //使用自定义mapper保存
                        isSave = handler.getMapper().insert(obj) > 0;
                    } else {
                        //保存原始对象
                        isSave = this.saveOrUpdate(obj);
                    }
                } else {
                    //保存至redis时isSave要设置为true来执行complete事件
                    isSave = true;
                }
            }
        }
        if (!isSave && FlymeUtils.isEmpty(obj)) {
            //保存原始对象
            obj = (T) JsonUtils.jsonToBean(JSONUtil.toJsonStr(cs.getRequestMap()), cs.getCls());
            isSave = this.saveOrUpdate(obj);
        }

        if (isSave) {
            resultBody = resultBody.ok("保存成功", obj);
            if (hasHandler) {
                //保存成功后调用扩展事件
                handler.complete(cs, cs.getRequestMap(), obj);
            }

        }
        return resultBody;

    }


    /**
     * List<EntityMap>
     *
     * @param cq
     * @return
     */
    @Override
    public List<EntityMap> selectEntityMap(CriteriaQuery<?> cq) {
        ApiAssert.isNotEmpty("服务器异常", cq.getCls());
        return baseMapper.selectEntityMap(cq);
    }

    /**
     * 根据条件构造器查询List<EntityMap>
     */
    public ResultBody listEntityMap(CriteriaQuery<?> cq) {
        ResultBody resultBody = new ResultBody();
        EntityMap extra = resultBody.getExtra();
        Boolean hanHandler = false;
        //获取扩展事件名称
        ListInterceptor handler = SpringContextHolder.getHandler(cq.getHandlerName(), ListInterceptor.class);
        if (ObjectUtils.isNotEmpty(handler)) {
            hanHandler = true;
            //执行校验
            resultBody = handler.validate(cq, cq.getRequestMap());
        }
        if (resultBody.isOk()) {
            //扩展查询条件
            if (hanHandler) {
                handler.prepare(cq, cq.getListModel(), cq.getRequestMap());
            }
            List<EntityMap> result = baseMapper.selectEntityMap(cq);
            if (ObjectUtils.isNotNull(result)) {
                //扩展查询结果集
                if (hanHandler) {
                    handler.complete(cq, result, extra);
                }
            }
            resultBody = resultBody.data(result).setExtra(extra);
        }
        return resultBody;
    }

    /**
     * 自定义sql查询List<EntityMap>
     */
    public List<EntityMap> listEntityMap(String statement, EntityMap map) {
        if (ObjectUtils.isEmpty(map)) {
            return null;
        }
        return sqlSession.selectList(getMapperName() + statement, map);
    }

    /**
     * 自定义sql查询List<EntityMap>
     */
    public List<EntityMap> listEntityMap(String statement, @Param("ew") CriteriaQuery<?> cq) {
        return sqlSession.selectList(getMapperName() + statement, cq);
    }


    /**
     * 获取mapperName
     */
    private String getMapperName() {
        String mapperName = "";
        Class cl = baseMapper.getClass();
        Class<?> interfaces[] = cl.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            mapperName = anInterface.getName();
        }
        return mapperName + ".";
    }

    public List<T> selectAll() {
        return this.baseMapper.selectList(null);
    }


}
